package com.tbit.uqbike.webmanager.util.collection;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Pair;

import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Set 工具类
 *
 *
 * @author <a href="mailto:chen.chaoxiong@tbit.com.cn">ChenChaoXiong</a>
 * @since 2024/7/11
 */
public class SetUtil {
    /**
     * 计算两个集合的笛卡尔积。
     * <p>给定两个集合，返回一个包含所有可能的唯一对组合的集合，其中第一个元素来自第一个集合，第二个元素来自第二个集合。</p>
     *
     * @param set1 第一个集合，不限类型
     * @param set2 第二个集合，不限类型
     * @return 一个包含所有可能对的集合
     */
    public static <F, S> Set<Pair<F, S>> cartesianProduct(Set<F> set1, Set<S> set2) {
        if (CollectionUtil.isEmpty(set1) || CollectionUtil.isEmpty(set2)) {
            return Collections.emptySet();
        }
        return set1.stream()
                   .flatMap(f -> set2.stream()
                                     .map(s -> new Pair<>(f, s)))
                   .collect(Collectors.toSet());
    }

    /**
     * 从第一个集合中排除第二个集合中存在的元素。
     * <p>此方法返回一个新集合，包含所有存在于第一个集合但不在第二个集合中的元素。</p>
     *
     * @param set1 第一个集合，元素为Pair对象
     * @param set2 第二个集合，元素为Pair对象
     * @return 一个新集合，包含所有在第一个集合但不在第二个集合中的元素
     */
    public static <F, S> Set<Pair<F, S>> exclusiveElementsFromFirstSet(Set<Pair<F, S>> set1, Set<Pair<F, S>> set2) {
        if (CollectionUtil.isEmpty(set1)) {
            return Collections.emptySet();
        }
        if (CollectionUtil.isEmpty(set2)) {
            return set1;
        }
        return set1.stream()
                   .filter(pair -> !set2.contains(pair))
                   .collect(Collectors.toSet());
    }
}
